Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BenefitInliner: Add structural analysis by using given CFG and add _hasBackEdges flag when generating CFG #7268

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mingweiarthurli
Copy link
Contributor

@mingweiarthurli mingweiarthurli commented Feb 16, 2024

Issue: #5488

Please merge this PR before merging eclipse-openj9/openj9#17813!

This is a pre-requisite PR of eclipse-openj9/openj9#17813, which used _hasBackEdges flag to determine if the generated CFG has back edges, and then used the generated CFG to generate the dominators and perform structural analysis. The structural analysis of using the given CFG enables the BenefitInliner to performance abstract interpretation for loop.

@mingweiarthurli mingweiarthurli changed the title BenefitInliner: Add structual analysis by using given CFG and add _hasBackEdges flag when generating CFG BenefitInliner: Add structural analysis by using given CFG and add _hasBackEdges flag when generating CFG Feb 16, 2024
@mingweiarthurli
Copy link
Contributor Author

mingweiarthurli commented Feb 16, 2024

Hi @jdmpapin, could you please take a look for this PR? Thank you! This is a pre-requisition by eclipse-openj9/openj9#17813, which are some code for handling loop by the BenefitInliner.

These changes were commited in eclipse-openj9/openj9#17813, but I treated them as obsolete code by mistake and discarded them. I'm sorry for the confusion and thank you very much for taking time to review this extra PR.

Since you had some questions for the changes in last PR, I will answer all of them at once now.

Thank you for your time in advance!

@mingweiarthurli
Copy link
Contributor Author

Currently the macOS check is failed, and the terminal ouput are following:

2: Traceback (most recent call last):
2:   File "/Users/runner/work/1/s/jitbuilder/apigen/test/cppgentests.py", line 128, in test_to_opaque_cast_2
2:     self.assertRegexpMatches(self.generator.to_opaque_cast("bar", class_desc),
2:     ^^^^^^^^^^^^^^^^^^^^^^^^
2: AttributeError: 'CppGeneratorTest' object has no attribute 'assertRegexpMatches'
2: 
2: ----------------------------------------------------------------------
2: Ran 143 tests in 0.845s
2: 
2: FAILED (errors=25, skipped=3)
2: warning: The package 'jsonschema' is not installed so certain tests will be skipped
32/49 Test  #2: TestJitBuilderAPIGenerator ..........***Failed    1.01 sec

This is still a known issue of #7181.

Copy link
Contributor

@jdmpapin jdmpapin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the refactoring here!

First I want to mention that there's a merge conflict. Could you please rebase to fix the conflict and push before making any other changes? Rebasing will introduce many changes compared to the current revision of the branch, and doing it this way will keep those separate from the meaningful changes that follow

I run the testcase of Jython and set breakpoint after if (_topDfNum != _numNodes-1) in our constructor, and I do found sometimes the breakpoint will be triggered. It seems the CFG gotten from the IDTNode's call target sometimes contains the unreachable blocks, and we don't want them, so the newly added TR_RegionAnalysis::getRegions() will do an early return once the dominator constructor found there is any unreachable blocks.

The problem is: TR_ASSERT seems just mapped to void(0) and will do nothing, so the former contributor chose to use _isValid to represent if the dominator detected any unreachable blocks.
I refactored this part and changed to use _hasUnreachableBlocks to represent existing unreachable block for code clarity.

OK. I think the real problem is that there are unreachable blocks in the CFG. They shouldn't be generated, or they should be removed before we get to this point. The TR_ASSERT is only checked in debug builds, but it's clearly stating that unreachable blocks are expected to be impossible here. I think we should probably change it to TR_ASSERT_FATAL so that it will fail in production builds as well

However, I don't want to delay this PR any further to deal with the fallout of that kind of change. So I'm OK with the general strategy already implemented here. The relaxation of the assertion is limited to the case where a CFG is passed explicitly, which will only be in the benefit inliner. But I have some comments about the details

@@ -357,6 +358,9 @@ class CFG
IsOrphanedRegion
};

void setHasBackEdges() { _hasBackEdges = true; }
bool hasBackEdges() { return _hasBackEdges; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This state isn't meaningfully set or used in this PR - I assume it's used in eclipse-openj9/openj9#17813

Does this need to be on the CFG? Or could it be kept somewhere else instead? e.g. next to a CFG pointer in the code that cares about it. I'm just worried that it will easily get out of date. In fact, with the fixed initial value (false), it will immediately be out of date for many CFGs. (And that would still be the case if the fixed initial value were true instead.)

@@ -110,15 +124,22 @@ TR_Dominators::TR_Dominators(TR::Compilation *c, bool post) :
traceMsg(comp(), "Some blocks are not reachable from exit. Post-dominator info is invalid.\n");
return;
}
if (!acceptUnreachableBlocks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the name acceptUnreachableBlocks is misleading - it's almost exactly backwards. The assertion isn't there to accept/ignore unreachable blocks. Rather, it's there to crash if it finds one

It might be better to have the name describe the input, e.g. what do you think of cfgMayContainUnreachableBlocks? If that's true, then we have to deal with the unreachable blocks (by indicating that they were found), and otherwise we can fail the assertion because they aren't supposed to be there

@@ -110,15 +124,22 @@ TR_Dominators::TR_Dominators(TR::Compilation *c, bool post) :
traceMsg(comp(), "Some blocks are not reachable from exit. Post-dominator info is invalid.\n");
return;
}
if (!acceptUnreachableBlocks)
{
_hasUnreachableBlocks = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please stick with _isValid, which already has the same meaning, and remove _hasUnreachableBlocks

@@ -53,11 +53,14 @@ class TR_Dominators
TR_ALLOC(TR_Memory::Dominators)

TR_Dominators(TR::Compilation *, bool post = false);
TR_Dominators(TR::Compilation *, TR::CFG* cfg, bool acceptUnreachableBlocks = true, bool post = false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does acceptUnreachableBlocks need to be a parameter? I expect TR_RegionAnalysis::getRegions(...cfg...) to be the only use of this. It's a parameter there as well, but I think it probably doesn't need to be

TR::Block *getDominator(TR::Block *);
int dominates(TR::Block *block, TR::Block *other);

TR::Compilation * comp() { return _compilation; }
bool trace() { return _trace; }
bool isValid() { return _isValid; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment to isValid() that explains why it's now possible for this to be invalid? e.g. something like this:

   // HACK: Dominators should always be valid, but for some reason the benefit
   // inliner can pass a CFG with unreachable blocks.

{
_hasUnreachableBlocks = true;
if (trace())
traceMsg(comp(), "Unreachable block in the CFG %d %d\n", _topDfNum, _numNodes-1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this message mention that the dominators are therefore invalid, like in the postdominator case?

if (trace())
traceMsg(comp(), "Unreachable block in the CFG %d %d\n", _topDfNum, _numNodes-1);
return;
}
else
TR_ASSERT(false, "Unreachable block in the CFG %d %d", _topDfNum, _numNodes-1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding a TODO comment for changing this to TR_ASSERT_FATAL?

… when generating CFG

This is a part of the BenefitInliner contribution.

* Dominators.hpp, Dominators.cpp, StructuralAnalysis.hpp, StructuralAnalysis.cpp: add structural analysis by using given CFG.
* OMRCfg.hpp: add _hasBackEdges flag to mark having loop in the CFG.

Co-authored-by: Cijie Xia <[email protected]>
Signed-off-by: Mingwei Li <[email protected]>
@mingweiarthurli
Copy link
Contributor Author

mingweiarthurli commented Jul 15, 2024

Hi Devin, just would like to tell you that 2b08c10 is just a rebase of preexisting code. The previous conflict was caused by newly added code from OMR master branch at line 362 and newly added code from this PR at line 364-365 of OMRCfg.hpp. I kept both of them as a fix. Currently there wasn't any meaningful changes yet. I will submit them in my next force-pushed commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants